﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Zxb.DayWork.Core;

namespace Zxb.DayWork.Logic
{
    public class HomeWorkUpdateHitsWorker : BatchWorker
    {
        private enum DataType
        {
            LastDay = 1,Week = 7, Month=30
        }
        private enum HitsType
        {
            Company = 1,                //公司
            UserDesignerExtend = 2,     //设计师
            ReplyTask = 4,              //作品
            Cases = 5,                  //案例
            CompanyNews = 6 ,           //促销
            UserDealerExtend=7          //店铺主页
        } 

        protected override void ProcessData()
        {
            //HomeWorkUpdateHitsByDateType();
            HomeWork_Update_Hits();
            //UP_HomeWorkDianpuHits();
        }

        #region 按时间段类型统计 如天、周、月
        private static void HomeWorkUpdateHitsByDateType()
        {
            try
            {
                Update(GetObjectHits(DataType.LastDay, HitsType.Cases), "Cases", "LastDayHits", 0);
                Update(GetObjectHits(DataType.Week, HitsType.Cases), "Cases", "WeekHits", 0);
                Update(GetObjectHits(DataType.Month, HitsType.Cases), "Cases", "MonthHits", 0);

                Update(GetObjectHits(DataType.LastDay, HitsType.CompanyNews), "CompanyNews", "LastDayHits", 0);
                Update(GetObjectHits(DataType.Week, HitsType.CompanyNews), "CompanyNews", "WeekHits", 0);
                Update(GetObjectHits(DataType.Month, HitsType.CompanyNews), "CompanyNews", "MonthHits", 0);
            }
            catch (Exception ex)
            {
                Logger.InfoLog.Error("按时间段类型统计 如天、周、月（HomeWorkUpdateHitsByDateType）出错：:" + ex.Message);
            }
        }

        private static DataTable GetObjectHits(DataType datatype, HitsType hitsType)
        {
            DataTable dt = null;
            StringBuilder sbSql = new StringBuilder();
            sbSql.Append(" Declare @beginDate varchar(10)=CONVERT(VARCHAR(10),DATEADD(DAY,-" + (int)datatype + ",GETDATE()),120) ,@endDate varchar(10)=convert(varchar(10),getdate(),120) ");
            sbSql.Append(" select ObjectID,sum(RandCount) Hits_Count from [HitsWeiKe_Real] with(nolock) ");
            sbSql.Append(" where TypeID=" + (int)hitsType + " and VisitTime >= @beginDate and VisitTime < @endDate and ObjectID>0 group by ObjectID ");

            //Database db = DB.Home_logAdmin;
            //dt = db.ExecuteDataSet(db.GetSqlStringCommand(sbSql.ToString())).Tables[0];

            dt = DAL.ReadDt_Retry(DB.Home_logAdmin, sbSql.ToString());

            return dt;
        }
        #endregion

        #region 更新各部分总的点击量
        private static void HomeWork_Update_Hits()
        {
            try
            {
                int minID = GetMinID(" and ID=2 ");
                int maxID = GetMaxID();

                //Update(GetObjectHits(HitsType.Company, minID, maxID), "Company", "HitNum", 1);
                //Update(GetObjectHits(HitsType.UserDesignerExtend, minID, maxID), "UserDesignerExtend", "ClickCount", 1);
                //Update(GetObjectHits(HitsType.ReplyTask, minID, maxID), "ReplyTask", "NumHit", 1);
                //Update(GetObjectHits(HitsType.Cases, minID, maxID), "Cases", "Hits", 1);
                //Update(GetObjectHits(HitsType.CompanyNews, minID, maxID), "CompanyNews", "Hits", 1);

                DataTable dtCompany = GetObjectHits(HitsType.Company, minID, maxID);
                DataTable dtUser = GetObjectHits(HitsType.UserDesignerExtend, minID, maxID);
                DataTable dtReply = GetObjectHits(HitsType.ReplyTask, minID, maxID);
                DataTable dtCase = GetObjectHits(HitsType.Cases, minID, maxID);
                DataTable dtComNews = GetObjectHits(HitsType.CompanyNews, minID, maxID);

                if (dtCase != null && dtComNews != null && dtCompany != null && dtReply != null && dtUser != null)
                {
                    Update(dtCompany, "Company", "HitNum", 1);
                    Update(dtUser, "UserDesignerExtend", "ClickCount", 1);
                    Update(dtReply, "ReplyTask", "NumHit", 1);
                    Update(dtCase, "Cases", "Hits", 1);
                    Update(dtComNews, "CompanyNews", "Hits", 1);

                    UpdateMaxid(maxID, " and ID=2 ");
                }
                else
                {
                    Logger.InfoLog.Info("因有数据读取出错，本轮统计点击量未执行");
                }
                
            }
            catch (Exception ex)
            {
                Logger.InfoLog.Error("更新各部分总的点击量（HomeWork_Update_Hits）出错：:" + ex.Message);
            }
        }

       
        #endregion

        private static DataTable GetObjectHits(HitsType hitsType, int minID, int maxID)
        {
            DataTable dt = null;
            StringBuilder sbSql = new StringBuilder();
            sbSql.Append("select ObjectID,sum(RandCount) as Hits_Count from [HitsWeiKe_Real] with(nolock) ");
            sbSql.Append(" where ");
            sbSql.Append((int)hitsType == 2 ? " (TypeID=2 or TypeID=21)" : "TypeID=" + (int)hitsType);
            sbSql.Append(" and " + minID + "<ID and ID<=" + maxID + " and ObjectID>0 group by ObjectID;");

            //Database db = DB.Home_logAdmin;
            //dt = db.ExecuteDataSet(db.GetSqlStringCommand(sbSql.ToString())).Tables[0];

            dt = DAL.ReadDt_Retry(DB.Home_logAdmin, sbSql.ToString());

            return dt;
        }

        public static void GetObjectTest()
        {
            DataTable dt = GetObjectHits(HitsType.Cases, 19978608, 20120608);
            int c = dt.Rows.Count;
        }
        public static void UpCaseHitTest()
        {
            DataTable dt = GetObjectHits(HitsType.Cases, 19000608, 19100608);//19000608
            Update(dt, "Cases", "Hits", 1);
        }
        public static void UpCompanyNewsTest()
        {
            DataTable dt = GetObjectHits(HitsType.CompanyNews, 19000608, 19400608);//19000608
            Update(dt, "CompanyNews", "Hits", 1);
        }

        #region 店铺点击量更新

        private static void UP_HomeWorkDianpuHits()
        {
            SqlConnection sqlConn = null;
            try
            {
                int minID = GetMinID(" and StatusName='HitsWeiKe 店铺点击量统计位置,最大ID' ");
                int maxID = GetMaxID();
                DataTable dt5 = GetObjectHits(HitsType.Cases, minID, maxID);
                DataTable dt6 = GetObjectHits(HitsType.CompanyNews, minID, maxID);
                DataTable dt7 = GetObjectHits(HitsType.UserDealerExtend, minID, maxID);

                sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["TaskWriter"].ConnectionString);

                SqlCommand cmd = new SqlCommand("UP_HomeWorkDianpuHits", sqlConn);

                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter tvpParam5 = cmd.Parameters.AddWithValue("@objectHits5", dt5);
                tvpParam5.SqlDbType = SqlDbType.Structured;
                tvpParam5.TypeName = "ObjectHits";
                SqlParameter tvpParam6 = cmd.Parameters.AddWithValue("@objectHits6", dt6);
                tvpParam6.SqlDbType = SqlDbType.Structured;
                tvpParam6.TypeName = "ObjectHits";
                SqlParameter tvpParam7 = cmd.Parameters.AddWithValue("@objectHits7", dt7);
                tvpParam7.SqlDbType = SqlDbType.Structured;
                tvpParam7.TypeName = "ObjectHits";

                //sqlConn.Open();
                //cmd.ExecuteNonQuery();
                //UpdateMaxid(maxID, " and StatusName='HitsWeiKe 店铺点击量统计位置,最大ID' ");

                bool flag = false;
                int retry = 5;
                for (int i = 0; i < retry; i++)
                {
                    try
                    {
                        sqlConn.Open();
                        cmd.ExecuteNonQuery();//曾出现过超过2分钟而不结束的情况，但会在约1小时后抛异常退出
                        flag = true;

                    }
                    catch (Exception ex)
                    {
                        Logger.InfoLog.Info(string.Format("执行存储过程{1}时错误：{0}, retry:{2}", ex.Message, "UP_HomeWorkDianpuHits", i));
                    }
                    finally
                    {
                        sqlConn.Close();
                    }
                    if (flag)
                    {
                        break;
                    }
                }
                if (flag)
                {
                    UpdateMaxid(maxID, " and StatusName='HitsWeiKe 店铺点击量统计位置,最大ID' ");
                    Logger.InfoLog.Info(string.Concat("UP_HomeWorkDianpuHits", "执行成功"));
                }
                else
                {
                    Logger.InfoLog.Error(string.Concat("UP_HomeWorkDianpuHits", "执行5次均出错"));
                }
                //return flag;
            }
            catch (Exception ex)
            {
                Logger.InfoLog.Error("更新点击量（UP_HomeWorkDianpuHits）出错：:" + ex.Message);
            }
            finally
            {
                if (sqlConn != null)
                {
                    sqlConn.Close();
                }
            }
        }

        #endregion

        /// <summary>
        /// 更新点击量基本方法
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="tableName"></param>
        /// <param name="fieldName"></param>
        private static void Update(DataTable dt, string tableName, string fieldName, int isAdd)
        {
            if (dt == null)
            {
                return;
            }
            if (dt.Rows.Count == 0)
            {
                Logger.InfoLog.Warn(string.Concat(tableName, ",count=0,", fieldName));
                return;
            }

            SqlConnection sqlConn = null;
            try
            {
                sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["TaskWriter"].ConnectionString);

                SqlCommand cmd = new SqlCommand("UP_HomeWorkBaseHits", sqlConn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandTimeout = 120;

                SqlParameter tvpParam = cmd.Parameters.AddWithValue("@objectHits", dt);
                tvpParam.SqlDbType = SqlDbType.Structured;
                tvpParam.TypeName = "ObjectHits";
                cmd.Parameters.AddWithValue("@tabName", tableName);
                cmd.Parameters.AddWithValue("@fieldName", fieldName);
                cmd.Parameters.AddWithValue("@isAdd", isAdd);

                //sqlConn.Open();

                //if (dt != null && dt.Rows.Count > 0)
                //{
                //    cmd.ExecuteNonQuery();
                //}

                string procedureName = string.Concat("UP_HomeWorkBaseHits:", tableName);
                bool flag = false;
                int retry = 5;
                for (int i = 0; i < retry; i++)
                {
                    try
                    {
                        sqlConn.Open();
                        cmd.ExecuteNonQuery();//曾出现过超过2分钟而不结束的情况，但会在约1小时后抛异常退出
                        flag = true;

                    }
                    catch (Exception ex)
                    {
                        Logger.InfoLog.Warn(string.Format("执行存储过程{1}时错误：{0}, retry:{2}", ex.Message, procedureName, i));
                    }
                    finally
                    {
                        sqlConn.Close();
                    }
                    if (flag)
                    {
                        break;
                    }
                }
                if (flag)
                {
                    Logger.InfoLog.Info(string.Concat(procedureName, "执行成功"));
                }
                else
                {
                    Logger.InfoLog.Error(string.Concat(procedureName, "执行5次均出错"));
                }
            }
            catch (Exception ex)
            {
                Logger.InfoLog.Error("更新点击量（方法名：Update；参数：tableName:" + tableName + ",fieldName:" + fieldName + ",isAdd:" + isAdd + "）出错：:" + ex.Message);
            }
            finally
            {
                if (sqlConn != null)
                {
                    sqlConn.Close();
                }
            }
        }

        private static int GetMinID(string sqlWhere)
        {
            int minid = 0;
            string sql = "select StatusValue from dbo.SiteStatus where 1=1 " + sqlWhere;
            Database db = DB.TaskReader;
            DbCommand selCmd = db.GetSqlStringCommand(sql);
            DataTable sleDT = db.ExecuteDataSet(selCmd).Tables[0];
            if (sleDT != null && sleDT.Rows.Count > 0)
            {
                minid = int.Parse(sleDT.Rows[0]["StatusValue"].ToString());
            }
            return minid;
        }

        private static int GetMaxID()
        {
            int maxid = 0;
            string sql = " select MAX(ID) maxid from dbo.HitsWeiKe_Real with(nolock) ";
            Database db = DB.Home_logAdmin;
            DbCommand selCmd = db.GetSqlStringCommand(sql);
            DataTable sleDT = db.ExecuteDataSet(selCmd).Tables[0];
            if (sleDT != null && sleDT.Rows.Count > 0)
            {
                maxid = int.Parse(sleDT.Rows[0]["maxid"].ToString());
            }
            return maxid;
        }

        private static void UpdateMaxid(int statusValue,string sqlWhere)
        {
            Database db = DB.TaskWriter;
            string upSql = " update SiteStatus set StatusValue=" + statusValue + " where 1=1 " + sqlWhere;
            DbCommand upCmd = db.GetSqlStringCommand(upSql);

            db.ExecuteNonQuery(upCmd);

            Logger.InfoLog.Info(string.Concat(sqlWhere, ",hit表已统计的最大位置=", statusValue));
        }

        protected override void ReadData()
        {

        }
        protected override void WriteData()
        {

        }
    }
}
